package com.example.testng.utils;

import io.qameta.allure.Allure;
import io.qameta.allure.Epic;
import io.qameta.allure.Feature;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

import java.io.File;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * Allure报告实时监听器，记录测试执行状态和结果
 */
public class AllureRealtimeListener implements ITestListener {
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public void onTestStart(ITestResult result) {
        log("开始执行测试: " + result.getName());
    }

    @Override
    public void onTestSuccess(ITestResult result) {
        log("测试通过: " + result.getName());
        attachTestDetails(result, "PASSED");
    }

    @Override
    public void onTestFailure(ITestResult result) {
        log("测试失败: " + result.getName());
        if (result.getThrowable() != null) {
            log("失败原因: " + result.getThrowable().getMessage());
        }
        attachTestDetails(result, "FAILED");
    }

    @Override
    public void onTestSkipped(ITestResult result) {
        log("测试跳过: " + result.getName());
        attachTestDetails(result, "SKIPPED");
    }

    @Override
    public void onStart(ITestContext context) {
        log("测试套件开始执行: " + context.getName());
    }

    @Override
    public void onFinish(ITestContext context) {
        int passed = context.getPassedTests().size();
        int failed = context.getFailedTests().size();
        int skipped = context.getSkippedTests().size();
        log(String.format("测试套件执行完成: %s\n通过: %d, 失败: %d, 跳过: %d",
                context.getName(), passed, failed, skipped));
    }

    private void log(String message) {
        String timestamp = LocalDateTime.now().format(formatter);
        System.out.println("[" + timestamp + "] " + message);
    }

    private void attachTestDetails(ITestResult result, String status) {
        try {
            // 添加测试执行时间信息
            long executionTime = result.getEndMillis() - result.getStartMillis();
            String details = String.format(
                "测试方法: %s\n" +
                "状态: %s\n" +
                "执行时间: %d ms\n" +
                "开始时间: %s\n" +
                "结束时间: %s",
                result.getName(),
                status,
                executionTime,
                formatMillis(result.getStartMillis()),
                formatMillis(result.getEndMillis())
            );

            // 将详细信息附加到Allure报告
            Allure.addAttachment("测试执行详情", details);

            // 如果测试失败，添加异常信息
            if (result.getThrowable() != null) {
                Allure.addAttachment(
                    "异常详情",
                    result.getThrowable().toString() + "\n" +
                    stackTraceToString(result.getThrowable())
                );
            }
        } catch (Exception e) {
            System.err.println("添加Allure附件时发生错误: " + e.getMessage());
        }
    }

    private String formatMillis(long millis) {
        return LocalDateTime.now()
            .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
    }

    private String stackTraceToString(Throwable throwable) {
        StringBuilder sb = new StringBuilder();
        for (StackTraceElement element : throwable.getStackTrace()) {
            sb.append("\tat ").append(element.toString()).append("\n");
        }
        return sb.toString();
    }
}